home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / find.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  20.5 KB  |  764 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 14
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. #pragma load EUDORA_LOAD
  4. #pragma segment Find
  5.  
  6. /************************************************************************
  7.  * structure to keep track of what we're finding
  8.  ************************************************************************/
  9. typedef struct {
  10.     Str255 what;                                    /* the string we're finding */
  11.     short onBox;                                    /* the mailbox we're currently looking in */
  12.     short onByte;                                 /* current position in message */
  13.     short onMessage;                            /* the message we're currently looking in */
  14.     short onField;                                /* for comp messages, the field we're in */
  15.     short findType;                             /* message, box, any box, alias */
  16.     MyWindowPtr dlog;                         /* our dialog, if any */
  17.     TOCHandle tocH;                             /* current toc */
  18.     MessHandle messH;                         /* current message */
  19.     Boolean openedBox;                        /* we opened the TOC (may need to close it) */
  20.     Boolean openedMess;                     /* we opened the message (may need to close) */
  21. } FindVars, *FindPtr, **FindHandle;
  22. FindHandle FG;
  23.  
  24. #define What (*FG)->what
  25. #define OnBox (*FG)->onBox
  26. #define OnMessage (*FG)->onMessage
  27. #define OnField (*FG)->onField
  28. #define OnByte (*FG)->onByte
  29. #define FindType (*FG)->findType
  30. #define Dlog (*FG)->dlog
  31. #define TocH (*FG)->tocH
  32. #define MessH (*FG)->messH
  33. #define OpenedBox (*FG)->openedBox
  34. #define OpenedMess (*FG)->openedMess
  35.  
  36. /************************************************************************
  37.  * private functions
  38.  ************************************************************************/
  39.     void DoFindDialog(void);
  40.     void RestartFind(void);
  41.     short InitFind(void);
  42.     short BoxNumber(TOCHandle tocH);
  43.     TOCHandle BoxByNumber(short boxNum,Boolean *opened);
  44.     MyWindowPtr FindTopUserWindow(void);
  45.     Boolean FindClose(MyWindowPtr win);
  46.     Boolean FindHit(EventRecord *event,DialogPtr dlog,short item);
  47.     Boolean FindMenu(MyWindowPtr win, int menu, int item, short modifiers);
  48.     void DoFindOK(void);
  49.     Boolean DoCompFind(Boolean allowWrap);
  50.     Boolean DoMessFind(Boolean allowWrap);
  51.     void PrimeByTxe(void);
  52.     short FindInTeh(TEHandle teh);
  53.     short FindSub(UPtr sub,UHandle    text,short offset);
  54.     short GrabFindTOC(void);
  55.     short GrabFindMessage(void);
  56.     void ReportFindFailure(void);
  57.     void FindCursor(Point mouse);
  58.     void EnterSelection(TEHandle teh);
  59.     long FindByteOffset(UPtr sub,UPtr buffer);
  60.     Boolean FindPSub(UPtr sub, UPtr string);
  61.     void CloseFindMess(void);
  62.     void CloseFindBox(void);
  63.  
  64. #pragma segment Main
  65. /************************************************************************
  66.  * EnableFindMenu - do the enabling for the find menu
  67.  ************************************************************************/
  68. void EnableFindMenu(void)
  69. {
  70.     MyWindowPtr win = FindTopUserWindow();
  71.     MenuHandle mh = GetMHandle(FIND_HIER_MENU);
  72.     Boolean myWindow = win && IsMyWindow(win);
  73.     Boolean notAlias = !myWindow ||
  74.                                             myWindow && win->qWindow.windowKind != ALIAS_WIN;
  75.     Boolean notBox = !myWindow ||
  76.                                         myWindow && win->qWindow.windowKind != MBOX_WIN &&
  77.                                                              win->qWindow.windowKind != CBOX_WIN;
  78.     
  79.     if (notAlias)
  80.     {
  81.         EnableItem(GetMHandle(EDIT_MENU),EDIT_FIND_ITEM);
  82.         EnableItem(mh,0);
  83.         EnableIf(mh,FIND_ENTER_ITEM,win&&win->hasSelection);
  84.         EnableIf(mh,FIND_AGAIN_ITEM,FG && *What);
  85.         EnableIf(mh,FIND_NEXT_ITEM,FG && *What);
  86.         EnableIf(mh,FIND_NEXT_MESS_ITEM,FG && *What);
  87.         EnableIf(mh,FIND_NEXT_BOX_ITEM,FG && *What);
  88.     }
  89.     else
  90.     {
  91.         DisableItem(GetMHandle(EDIT_MENU),EDIT_FIND_ITEM);
  92.         DisableItem(mh,0);
  93.     }
  94. }
  95.  
  96. #pragma segment Find
  97. /************************************************************************
  98.  * DoFind - handle the user choosing find
  99.  ************************************************************************/
  100. void DoFind(short item)
  101. {
  102.     MyWindowPtr win;
  103.     if (InitFind()) return;
  104.     
  105.     RestartFind();
  106.     PrimeByTxe();
  107.     
  108.     switch (item)
  109.     {
  110.         case FIND_FIND_ITEM:
  111.             DoFindDialog();
  112.             return;
  113.             break;
  114.         case FIND_NEXT_ITEM:
  115.             FindType = FDL_NEXT;
  116.             break;
  117.         case FIND_NEXT_MESS_ITEM:
  118.             FindType = FDL_NEXT;
  119.             OnMessage++;
  120.             break;
  121.         case FIND_NEXT_BOX_ITEM:
  122.             FindType = FDL_NEXT;
  123.             if (TocH) OnMessage = (*TocH)->count;
  124.             break;
  125.         case FIND_ENTER_ITEM:
  126.             OpenedBox = OpenedMess = False;
  127.             win = FindTopUserWindow();
  128.             if (win && WinTEH(win) && win->hasSelection)
  129.                 EnterSelection(WinTEH(win));
  130.             return;
  131.             break;
  132.     }
  133.     DoFindOK();
  134. }
  135.  
  136. /************************************************************************
  137.  * Boolean FindHit - a hit on an enabled item in the Find box
  138.  * the return value should be true if the main loop needs to do
  139.  * something with event, false if the main loop can safely ignore it
  140.  ************************************************************************/
  141. Boolean FindHit(EventRecord *event,DialogPtr dlog,short item)
  142. {
  143. #pragma unused(event);
  144.     Str255 scratch;
  145.     
  146.     if (item==FDL_CANCEL)
  147.     {
  148.         CloseMyWindow(dlog);
  149.         return(False);
  150.     }
  151.     
  152.     GetDIText(dlog,FDL_TEXT,scratch);
  153.     PCopy(What,scratch);
  154.  
  155.     RestartFind();
  156.     PrimeByTxe();
  157.         
  158.     switch(item)
  159.     {
  160.         case FDL_NEXT:
  161.             FindType = FDL_NEXT;
  162.             break;
  163.         case FDL_NEXT_MESS:
  164.             FindType = FDL_NEXT;
  165.             OnMessage++;
  166.             break;
  167.         case FDL_NEXT_BOX:
  168.             FindType = FDL_NEXT;
  169.             if (TocH) OnMessage = (*TocH)->count;
  170.             break;
  171.         case FDL_SENSITIVE:
  172.             ChangeStrn(PREF_STRN,PREF_SENSITIVE,
  173.                                     PrefIsSet(PREF_SENSITIVE)?"\pn":"\py");
  174.             SetDItemState(Dlog,FDL_SENSITIVE,PrefIsSet(PREF_SENSITIVE));
  175.             return(False);
  176.         case FDL_TEXT:
  177.             OpenedBox = OpenedMess = False;
  178.             return(False);
  179.         case FDL_SUM_ONLY:
  180.             ChangeStrn(PREF_STRN,PREF_SUM_ONLY,
  181.                                     PrefIsSet(PREF_SUM_ONLY)?"\pn":"\py");
  182.             SetDItemState(Dlog,FDL_SUM_ONLY,PrefIsSet(PREF_SUM_ONLY));
  183.             return(False);
  184.     }
  185.     DoFindOK();
  186.     
  187.     return(False);
  188. }
  189.  
  190. /************************************************************************
  191.  * FindMenu - handle the menu items that must be handled for the find window
  192.  ************************************************************************/
  193. Boolean FindMenu(MyWindowPtr win, int menu, int item, short modifiers)
  194. {
  195. #pragma unused(modifiers)
  196.     switch(menu)
  197.     {
  198.         case EDIT_MENU:
  199.             (void) DoModelessEdit(win,item);
  200.             break;
  201.         default:
  202.             return(False);
  203.     }
  204.     return(True);
  205. }
  206.  
  207. /************************************************************************
  208.  * DoFindDialog - make the Find dialog box frontmost
  209.  ************************************************************************/
  210. void DoFindDialog(void)
  211. {
  212.     Str255 what;
  213.     if (InitFind()) return;
  214.     if (!Dlog)
  215.     {
  216.         DialogPtr grumble;
  217.         grumble = GetNewMyDialog(FIND_DLOG,nil,InFront,BottomCenterDialog);
  218.         if (!grumble)
  219.             {WarnUser(MEM_ERR,MemError()); return;}
  220.         Dlog = grumble;
  221.         Dlog->close = FindClose;
  222.         Dlog->menu = FindMenu;
  223.         Dlog->cursor = FindCursor;
  224.         Dlog->hit = FindHit;
  225.         Dlog->position = PositionPrefsTitle;
  226.         Dlog->hot = True;
  227.     }
  228.     PCopy(what,What);
  229.     SetDIText(Dlog,FDL_TEXT,what);
  230.     SetDItemState(Dlog,FDL_SENSITIVE,PrefIsSet(PREF_SENSITIVE));
  231.     SetDItemState(Dlog,FDL_SUM_ONLY,PrefIsSet(PREF_SUM_ONLY));
  232.     if (!((WindowPeek)Dlog)->visible)
  233.     {
  234.         if (Get1NamedResource(SAVE_POS_TYPE,
  235.                                                     LDRef(((WindowPeek)Dlog)->titleHandle)))
  236.             ShowMyWindow(Dlog);
  237.         else
  238.             ShowWindow(Dlog);
  239.         UL(((WindowPeek)Dlog)->titleHandle);
  240.     }
  241.     SelectWindow(Dlog);
  242.     SelIText(Dlog,FDL_TEXT,0,INFINITY);
  243.     RestartFind();
  244.     SFWTC = True;
  245. }
  246.  
  247. /************************************************************************
  248.  * RestartFind - re-initialize the find function
  249.  ************************************************************************/
  250. void RestartFind(void)
  251. {
  252.     MyWindowPtr win = FindTopUserWindow();
  253.     short oldOnMessage = OnMessage;
  254.     short oldOnBox = OnBox;
  255.     TOCHandle oldTocH = TocH;
  256.     
  257.     if (!FG) return;
  258.     FindType = FDL_NEXT;
  259.     OnBox = OnField = OnMessage = 0;
  260.     OnByte = -1;
  261.     TocH = MessH = nil;
  262.     if (win)
  263.     {
  264.         switch (win->qWindow.windowKind)
  265.         {
  266.             case MBOX_WIN:
  267.             case CBOX_WIN:
  268.                 FindType = FDL_NEXT;
  269.                 TocH = (TOCHandle) win->qWindow.refCon;
  270.                 OnBox = BoxNumber(TocH);
  271.                 break;
  272.             case COMP_WIN:
  273.             case MESS_WIN:
  274.                 FindType = FDL_FIND;
  275.                 MessH = (MessHandle) win->qWindow.refCon;
  276.                 TocH = (*MessH)->tocH;
  277.                 OnBox = BoxNumber(TocH);
  278.                 OnMessage = (*MessH)->sumNum;
  279.                 break;
  280.             case ALIAS_WIN:
  281.                 break;
  282.         }
  283.     }
  284.     if (OnBox!=oldOnBox || OnMessage!=oldOnMessage) {OpenedMess = OpenedBox = False;}
  285. }
  286.  
  287. /************************************************************************
  288.  * InitFind - get the find stuff ready to go
  289.  ************************************************************************/
  290. short InitFind(void)
  291. {
  292.     if (FG) return(0);
  293.     if ((FG=NewZH(FindVars))==nil) return(WarnUser(MEM_ERR,MemError()));
  294.     RestartFind();
  295.     return(0);
  296. }
  297.  
  298. /************************************************************************
  299.  * Box Numbering:
  300.  * Boxes are numbered almost as their positions in the mailbox menu.
  301.  * The differences are:
  302.  *     The separator line is ignored
  303.  *     The In, Out, and Trash boxes appear LAST, not FIRST
  304.  ************************************************************************/
  305. /************************************************************************
  306.  * BoxNumber - what number is a given toc?
  307.  ************************************************************************/
  308. short BoxNumber(TOCHandle tocH)
  309. {
  310.     Str31 name;
  311.     MenuHandle mh;
  312.     short item;
  313.     short num,n;
  314.     long dirId;
  315.     
  316.     n = GetHandleSize(BoxCount)/sizeof(BoxCountElem);
  317.     PCopy(name,(*tocH)->name);
  318.     dirId = (*tocH)->dirId;
  319.     mh = GetMHandle((dirId == MyDirId) ? MAILBOX_MENU : FindDirLevel(dirId));
  320.     item = FindItemByName(mh,name);
  321.     for (num=0;num<n;num++)
  322.         if ((*BoxCount)[num].item==item && (*BoxCount)[num].dirId==dirId)
  323.             return(num);
  324.     return(n);
  325. }
  326.  
  327. /************************************************************************
  328.  * BoxByNumber - return the toc of a box with a given number?
  329.  ************************************************************************/
  330. TOCHandle BoxByNumber(short boxNum,Boolean *opened)
  331. {
  332.     Str31 name;
  333.     TOCHandle tocH;
  334.     long dirId;
  335.     short menuId;
  336.     
  337.     *opened = False;
  338.     
  339.     if (boxNum>=GetHandleSize(BoxCount)/sizeof(BoxCountElem)) return(nil);
  340.     dirId = (*BoxCount)[boxNum].dirId;
  341.     menuId = (dirId==MyDirId) ? MAILBOX_MENU : FindDirLevel(dirId);
  342.     MyGetItem(GetMHandle(menuId),(*BoxCount)[boxNum].item,name);
  343.     
  344.     if (tocH=FindTOC((*BoxCount)[boxNum].dirId,name)) return(tocH);
  345.     
  346.     if (GetMailbox((*BoxCount)[boxNum].dirId,name,False)) return(nil);
  347.     *opened=True;
  348.     return(FindTOC((*BoxCount)[boxNum].dirId,name));
  349. }
  350.  
  351. /************************************************************************
  352.  * FindTopUserWindow - find the topmost (non-find) user window
  353.  ************************************************************************/
  354. MyWindowPtr FindTopUserWindow(void)
  355. {
  356.     WindowPeek win;
  357.     
  358.     for (win=FrontWindow();win;win = win->nextWindow)
  359.         if (win->visible && win->windowKind>userKind && win->windowKind!=FIND_WIN)
  360.             return(win);
  361.     return(nil);
  362. }
  363.  
  364. /************************************************************************
  365.  * FindClose - close the find window
  366.  ************************************************************************/
  367. Boolean FindClose(MyWindowPtr win)
  368. {
  369. #pragma unused(win)
  370.     Dlog = nil;
  371.     return(True);
  372. }
  373.  
  374. /************************************************************************
  375.  * DoFindOK - continue with our find
  376.  ************************************************************************/
  377. void DoFindOK(void)
  378. {
  379.     MyWindowPtr win = FindTopUserWindow();
  380.     short kind=win->qWindow.windowKind;
  381.     short startBox = OnBox;
  382.     short startMessage = OnMessage;
  383.     Boolean wrapped = False;
  384.     short nBoxes = GetHandleSize(BoxCount)/sizeof(BoxCountElem);
  385.     Str63 outName,name;
  386.     EventRecord event;
  387.     long pTicks;
  388.     
  389.     if (!*What) return;                                     /* nothing to find */
  390.     GetRString(outName,OUT);
  391.     CycleBalls();
  392.     
  393.     switch (FindType)
  394.     {
  395.         case FDL_FIND:
  396.             if (kind==COMP_WIN)
  397.             {
  398.                 if (!DoCompFind(True)) ReportFindFailure();
  399.             }
  400.             else if (kind==MESS_WIN)
  401.             {
  402.                 if (!DoMessFind(True)) ReportFindFailure();
  403.             }
  404.             break;
  405.         case FDL_NEXT:
  406.             do
  407.             {
  408.                 CycleBalls();
  409.                 if (WNE(everyEvent,&event,0))
  410.                 {
  411.                     (void) MiniMainLoop(&event);
  412.                     if (CommandPeriod) break;
  413.                 }
  414.                 if (OnBox >= nBoxes)
  415.                 {
  416.                     OnBox = OnMessage = 0;
  417.                     OnByte = -1;
  418.                     wrapped = True;
  419.                     continue; /* try the checks again */
  420.                 }
  421.                 if (GrabFindTOC()) break;
  422.                 if (OnMessage < (*TocH)->count)
  423.                 {
  424.                     if ((*TocH)->sums[OnMessage].length < INFINITY)
  425.                     {
  426.                         if (TickCount()-pTicks > 5 || !OnMessage || OnMessage+1==(*TocH)->count)
  427.                         {
  428.                             OpenProgress();
  429.                             Progress(((OnMessage+1)*100)/(*TocH)->count,LDRef(TocH)->name);
  430.                             UL(TocH);
  431.                             pTicks = TickCount();
  432.                         }
  433.                         if (OnByte<0 && (FindPSub(What,(*TocH)->sums[OnMessage].subj) ||
  434.                                 FindPSub(What,(*TocH)->sums[OnMessage].from) ||
  435.                                 FindPSub(What,(*TocH)->sums[OnMessage].date)))
  436.                         {
  437.                             if (GrabFindMessage()) break;
  438.                             ShowMyWindow((*MessH)->win);
  439.                             SelectWindow((*MessH)->win);
  440.                             OnByte = 0;
  441.                             goto returnSpot;
  442.                         }
  443.                         if (OnByte<0) OnByte = 0;
  444.                         if (!PrefIsSet(PREF_SUM_ONLY))
  445.                         {
  446.                             if (GrabFindMessage()) break;
  447.                             PCopy(name,(*TocH)->name);
  448.                             if (EqualString(name,outName,False,True))
  449.                             {
  450.                                 if (DoCompFind(False)) goto returnSpot;
  451.                             }
  452.                             else
  453.                             {
  454.                                 if (DoMessFind(False)) goto returnSpot;
  455.                             }
  456.                         }
  457.                     }
  458.                     OnMessage++;
  459.                     OnByte = -1;
  460.                     OnField = 0;
  461.                 }
  462.                 else
  463.                 {
  464.                     OnBox++;
  465.                     OnMessage = OnField = 0;
  466.                     OnByte = -1;
  467.                 }
  468.             }
  469.             while (!(wrapped && OnBox==startBox && OnMessage >= startMessage));
  470.             CloseFindMess();
  471.             CloseFindBox();
  472.             if (!CommandPeriod) ReportFindFailure();
  473.             break;
  474.     }
  475. returnSpot:
  476.     CloseProgress();
  477. }
  478.  
  479. /************************************************************************
  480.  * DoCompFind - find in a comp message
  481.  ************************************************************************/
  482. Boolean DoCompFind(Boolean allowWrap)
  483. {
  484.     MyWindowPtr win = (*MessH)->win;
  485.     TEHandle teh;
  486.     short offset;
  487.     Boolean wasInMiddle = OnByte || OnField;
  488.     
  489.     while ((offset = FindInTeh((*MessH)->txes[OnField]))<0)
  490.     {
  491.         OnByte = 0;
  492.         OnField++;
  493.         if (OnField >= HEAD_LIMIT) break;
  494.     }
  495.     
  496.     if (offset>=0)
  497.     {
  498.         teh = (*MessH)->txes[OnField];
  499.         if (!win->qWindow.visible)
  500.             ShowMyWindow(win);
  501.         SelectWindow(win);
  502.         TESetSelect(offset,offset+*What,teh);
  503.         win->hasSelection = True;
  504.         OnByte = offset+*What;
  505.         if (teh != win->txe)
  506.         {
  507.             if (win->txe)
  508.                 TEDeactivate(win->txe);
  509.             TEActivate(teh);
  510.             win->txe = teh;
  511.             win->ro = (*MessH)->txRo[OnField];
  512.         }
  513.         ShowInsertion(win,InsertAny);
  514.         SFWTC=True;
  515.         return(True);
  516.     }
  517.     else if (wasInMiddle && allowWrap)
  518.     {
  519.         OnByte = OnField = 0;
  520.         return(DoCompFind(allowWrap));
  521.     }
  522.     else
  523.         return(False);
  524. }
  525.  
  526. /************************************************************************
  527.  * DoMessFind - find in the current message
  528.  ************************************************************************/
  529. Boolean DoMessFind(Boolean allowWrap)
  530. {
  531.     Boolean wasInMiddle = OnByte!=0;
  532.     MyWindowPtr win = (*MessH)->win;
  533.     short offset = FindInTeh(Win2Body(win));
  534.     if (offset>=0)
  535.     {
  536.         if (!win->qWindow.visible)
  537.             ShowMyWindow(win);
  538.         SelectWindow(win);
  539.         if ((*(STEHandle)win->ste)->te != Win2Body(win)) MessSwapTXE(MessH);
  540.         NoScrollTESetSelect(offset,offset+*What,Win2Body(win));
  541.         ShowInsertion((*MessH)->win,InsertAny);
  542.         (*MessH)->win->hasSelection = True;
  543.         OnByte = offset+*What;
  544.         TEActivate(Win2Body(win));
  545.         ShowInsertion(win,InsertAny);
  546.         SFWTC=True;
  547.         return(True);
  548.     }
  549.     else if (wasInMiddle && allowWrap)
  550.     {
  551.         OnByte = 0;
  552.         return(DoMessFind(allowWrap));
  553.     }
  554.     else
  555.         return(False);
  556. }
  557.  
  558. /************************************************************************
  559.  * PrimeByTxe - use the current selection point to prime the find software
  560.  ************************************************************************/
  561. void PrimeByTxe(void)
  562. {
  563.     MyWindowPtr win = FindTopUserWindow();
  564.     TEHandle teh;
  565.     
  566.     if (IsMyWindow(win) && win->qWindow.windowKind==MESS_WIN)
  567.         if ((*(STEHandle)win->ste)->te != Win2Body(win))
  568.             MessSwapTXE((MessHandle)win->qWindow.refCon);
  569.  
  570.     if (win && (teh=WinTEH(win)))
  571.     {
  572.         OnByte = (*teh)->selEnd;
  573.         if (win->qWindow.windowKind==COMP_WIN)
  574.             OnField = FindCompTx((MessHandle)win->qWindow.refCon,teh);
  575.     }
  576. }
  577.  
  578. /************************************************************************
  579.  * FindInTeh - find a string in a given text handle.
  580.  ************************************************************************/
  581. short FindInTeh(TEHandle teh)
  582. {
  583.     short length = (*teh)->teLength;
  584.     short offset;
  585.     
  586.     if (OnByte + *What > length) return(-1);
  587.     
  588.     offset = FindSub(What,(*teh)->hText,OnByte);
  589.     OnByte = offset;
  590.     if (offset>=length) return(-1);
  591.     return(offset);
  592. }
  593.  
  594. /************************************************************************
  595.  * FindPSub - find a pascal substring in a pascal string
  596.  ************************************************************************/
  597. Boolean FindPSub(UPtr sub, UPtr string)
  598. {
  599.     unsigned char buffer[254*2+1];
  600.     BlockMove(string+1,buffer,*string);
  601.     BlockMove(sub+1,buffer+*string,*sub);
  602.     sub[*sub+1] = buffer[*sub+*string] = 0;
  603.     return(FindByteOffset(sub+1,buffer)<*string);
  604. }
  605.  
  606. /************************************************************************
  607.  * FindSub - find a substring in some text. 
  608.  * Brute force.
  609.  ************************************************************************/
  610. short FindSub(UPtr sub,UHandle    text,short offset)
  611. {
  612.     long size = GetHandleSize(text);
  613.     short result = 0;
  614.     
  615.     if (PtrAndHand(sub+1,text,*sub+1))
  616.         return(size);
  617.     sub[*sub+1] = (*text)[size+*sub] = 0;
  618.     result = FindByteOffset(sub+1,*text+offset);
  619.     SetHandleBig(text,size);
  620.     return(result+offset);
  621. }
  622.  
  623. /************************************************************************
  624.  * FindByteOffset - find a substring in some text.
  625.  * Brute force.  Sub *must* be in buffer!!!!!  Each string should be NULL
  626.  * terminated.
  627.  ************************************************************************/
  628. long FindByteOffset(UPtr sub,UPtr buffer)
  629. {
  630.     UPtr anchor, spot, subSpot;
  631.     short result;
  632.     
  633.     if (PrefIsSet(PREF_SENSITIVE))
  634.     {
  635.         for (anchor = buffer;;anchor++)
  636.         {
  637.             for (spot=anchor,subSpot=sub;
  638.                      *spot==*subSpot && *subSpot;
  639.                      spot++,subSpot++);
  640.             if (!*subSpot)
  641.             {
  642.                 result = anchor - buffer;
  643.                 break;
  644.             }
  645.         }
  646.     }
  647.     else
  648.     {
  649.         for (anchor = buffer;;anchor++)
  650.         {
  651.             if (!striscmp(sub,anchor))
  652.             {
  653.                 result = anchor - buffer;
  654.                 break;
  655.             }
  656.         }
  657.     }
  658.     return(result);
  659. }
  660.  
  661. /************************************************************************
  662.  * GrabFindTOC - open the current toc
  663.  ************************************************************************/
  664. short GrabFindTOC(void)
  665. {
  666.     Boolean opened;
  667.     TOCHandle tocH;
  668.     
  669.     tocH = BoxByNumber(OnBox,&opened);
  670.     if (opened || tocH!=TocH)
  671.     {
  672.         CloseFindMess();
  673.         CloseFindBox();
  674.         OpenedBox = opened;
  675.     }
  676.     TocH = tocH;
  677.     return (!TocH);
  678. }
  679.  
  680. /************************************************************************
  681.  * GrabFindMessage - open the current message
  682.  ************************************************************************/
  683. short GrabFindMessage(void)
  684. {
  685.     Boolean opened=False;
  686.     if (!TocH) return(1);
  687.     if (!(*TocH)->sums[OnMessage].messH)
  688.     {
  689.         if (GetAMessage(TocH,OnMessage,nil,0)) opened = True;
  690.     }
  691.     if (MessH!=(*TocH)->sums[OnMessage].messH || opened)
  692.     {
  693.         CloseFindMess();
  694.         OpenedMess = opened;
  695.     }
  696.     MessH=(*TocH)->sums[OnMessage].messH;
  697.     return(!MessH);
  698. }
  699.  
  700.  
  701. /************************************************************************
  702.  * 
  703.  ************************************************************************/
  704. void CloseFindMess(void)
  705. {
  706.     if (MessH && OpenedMess)
  707.       CloseMyWindow((*MessH)->win);
  708.     OpenedMess = False;
  709.     MessH = nil;
  710. }
  711.  
  712. /************************************************************************
  713.  * 
  714.  ************************************************************************/
  715. void CloseFindBox(void)
  716. {
  717.     if (TocH && OpenedBox)
  718.       CloseMyWindow((*TocH)->win);
  719.     OpenedBox = False;
  720.     TocH = nil;
  721. }
  722.  
  723. /************************************************************************
  724.  * ReportFindFailure - just like it says
  725.  ************************************************************************/
  726. void ReportFindFailure(void)
  727. {
  728.     Str255 what;
  729.     PCopy(what,What);
  730.     AlertStr(NOT_FOUND_ALRT,Note,what);
  731. }
  732.  
  733. /************************************************************************
  734.  * FindCursor - set the cursor properly for the find window
  735.  ************************************************************************/
  736. void FindCursor(Point mouse)
  737. {
  738.     Rect r;
  739.     Handle itemH;
  740.     short type;
  741.     
  742.     itemH = nil;
  743.     GetDItem(Dlog,FDL_TEXT,&type,&itemH,&r);
  744.     if (itemH && CursorInRect(mouse,r,MouseRgn))
  745.         SetMyCursor(iBeamCursor);
  746.     else
  747.         SetMyCursor(arrowCursor);
  748. }
  749.  
  750. /************************************************************************
  751.  * EnterSelection - enter the selection from the current txe in the
  752.  * find window
  753.  ************************************************************************/
  754. void EnterSelection(TEHandle teh)
  755. {
  756.     int length = MIN(254,(*teh)->selEnd - (*teh)->selStart);
  757.     Str255 what;
  758.     
  759.     BlockMove(*(*teh)->hText + (*teh)->selStart,What+1,length);
  760.     *What = length;
  761.     PCopy(what,What);
  762.     if (Dlog) SetDIText(Dlog,FDL_TEXT,what);
  763. }
  764.